package com.downguys.microservice.start;

import com.downguys.microservice.Start;
import com.downguys.tool.netty.ByteBufManager;
import com.downguys.tool.netty.OspMessageDecoder;
import com.downguys.tool.netty.SslContextFactory;
import com.downguys.tool.netty.SslProviderUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author mingmin.zhou(弄死熊猫)
 * @mail 714387891@qq.com
 * @date 2017/7/18
 */
public class StartService implements Start {


    private static final Logger logger = LoggerFactory.getLogger(StartService.class);

    private NioEventLoopGroup bossGroup;

    private NioEventLoopGroup workGroup;

    @Override
    public void start(final boolean sslFlag) {
        bossGroup = new NioEventLoopGroup(1,new DefaultThreadFactory("boss-contain",true));
        workGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors()*2,new DefaultThreadFactory("boss-contain",true));
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup,workGroup);
        bootstrap.channel(NioServerSocketChannel.class);

        bootstrap.option(ChannelOption.SO_REUSEADDR, Boolean.TRUE).option(ChannelOption.ALLOCATOR,
                ByteBufManager.byteBufAllocator);
        bootstrap.childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)
                .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE)
                .childOption(ChannelOption.ALLOCATOR, ByteBufManager.byteBufAllocator);
        // .childOption(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, OspSystemEnvProperties.HIGH_WATER_MARK)
        // .childOption(ChannelOption.WRITE_BUFFER_LOW_WATER_MARK, OspSystemEnvProperties.LOW_WATER_MARK)
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                final String remoteAddress = ch.remoteAddress().toString();
                ChannelPipeline pipeline = ch.pipeline();
                logger.info("init channel from " + remoteAddress);
                if (sslFlag) { // 如果当前服务为SSL，则增加SSL的handler，处理握手交互
                    // logger.info("container begin ssl handshake from " + remoteAddress);
                    // 使用Netty的SSL API
                    SslContext sslCtx = SslContextFactory.getServerContext(SslProviderUtil.getSslProvider(), false); // SslContext工厂，获取全局共享的server端SslContext
                    SslHandler sslHandler = sslCtx.newHandler(ch.alloc());
                    sslHandler.handshakeFuture().addListener(new GenericFutureListener<Future<Channel>>() {
                        @Override
                        public void operationComplete(Future<Channel> future) throws Exception {
                            if (future.isSuccess()) {
                                logger.info("container finish ssl handshake from " + remoteAddress);
                            } else {
                                logger.warn("container fail ssl handshake, " + future.cause().getClass() + ':'
                                        + future.cause().getMessage());
                            }
                        }
                    });
                    pipeline.addLast(sslHandler);
                }

                pipeline.addLast(new OspMessageDecoder());
                pipeline.addLast(new ChannelInboundHandlerAdapter());
            }
        });





    }

    @Override
    public void stop() {

    }
}
